import { Global, Module, ValidationPipe } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import config from '../config/index';
import { ThrottlerGuard, ThrottlerModule, seconds } from "@nestjs/throttler";
import TimeoutInterceptor from '../common/interceptors/timeout.interceptor';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE, HttpAdapterHost } from '@nestjs/core';
import ExtenedPrismaConfigService from "./datebase/extended-prisma-config.service";
import { CustomPrismaModule, PrismaClientExceptionFilter, PrismaModule } from "nestjs-prisma";
import PrismaConfigService from "./datebase/prisma.config.service";
import { LoggerModule } from "./logger/logger.module";

import { RedisModule } from "@nestjs-modules/ioredis";
import { BullModule } from '@nestjs/bullmq';
import { SharedService } from "./shared.service";
import AllExceptionsFilter from "src/common/filters/exceptions.filter";
import JwtAuthGuard from "src/common/guards/jwt-auth.guard";

@Global()
@Module({
    imports: [
        LoggerModule.forRoot(),

        // 配置文件设置
        ConfigModule.forRoot({
            isGlobal: true,
            // 配置文件路径, 优先级：.env.local > .env.${process.env.NODE_ENV} > .env, 指定多个env文件
            envFilePath: ['.env.local', `.env.${process.env.NODE_ENV}`, '.env'],
            load: [config]
        }),

        // 避免暴力请求，限制同一个接口 10 秒内不能超过 30 次请求
        ThrottlerModule.forRootAsync({
            useFactory: () => ({
            errorMessage: '当前操作过于频繁，请稍后再试！',
            throttlers: [
                { ttl: seconds(10), limit: 30 },
            ],
            })
        }),

        // 导入Primsa数据库模块，使用类来加载，方便配置，
        // mysql 数据库的配置文件在 .env中，它内部会自动读取
        PrismaModule.forRootAsync({
            isGlobal: true,
            useClass: PrismaConfigService,
        }),


        /**
         * 增加prisma扩展客户端，方便业务操作
         * 可以自定义各种数据库操作方法。
         * 可以在数据库操作前做参数修改，在查询后做结果修改。
         */
        CustomPrismaModule.forRootAsync({
            isGlobal: true,
            name: "CustomPrisma",
            useClass: ExtenedPrismaConfigService,
        }),

        // redis设置
        RedisModule.forRootAsync({
            useFactory:(ConfigService: ConfigService) => {
                const redis = ConfigService.get('redis');
                return {
                    type: 'single',
                    url: `redis://:${redis.password}@${redis.host}:${redis.port}/${redis.db}`,
                  };
            },
            inject: [ConfigService],
        }),
        
        // 开启队列机制
        BullModule.forRootAsync({
            useFactory: (ConfigService: ConfigService) =>  {
                const redis = ConfigService.get('redis');
                return { connection: {
                    host: redis.host,
                    port: redis.port,
                }}
            },
            inject: [ConfigService],
        }),

    ],
    providers: [
        SharedService,
        // 全局异常过滤器
        { provide: APP_FILTER, useClass: AllExceptionsFilter },
        { provide: APP_FILTER, useFactory: ({ httpAdapter}: HttpAdapterHost) => new PrismaClientExceptionFilter(httpAdapter), inject: [HttpAdapterHost] },
        // app 开启全局日志
        {provide: APP_PIPE, useValue: new ValidationPipe({ whitelist: false, transform: true, transformOptions: { enableImplicitConversion: true }})},
        // 开启超时拦截
        { provide: APP_INTERCEPTOR, useFactory:() => new TimeoutInterceptor(60 * 1000)},

        // { provide: APP_GUARD, useClass: },
        // 
        { provide: APP_GUARD, useClass: ThrottlerGuard },
        // jwt验证守卫
        { provide: APP_GUARD, useClass: JwtAuthGuard },
    ],
    exports: [SharedService],
})

export class SharedModule {}